﻿using Castle.DynamicProxy;
using Lk.Common.AttributeHelper;
using Lk.Common.Cache;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Lk.Api.Aop
{
    public class CacheAop : IInterceptor
    {
        private readonly ICacheService _cacheService;

       
        public CacheAop(ICacheService cacheService)
        {
            _cacheService = cacheService;
        }
        public void Intercept(IInvocation invocation)
        {

            var method = invocation.MethodInvocationTarget ?? invocation.Method;
            var qCachingAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CachingAttribute)) as CachingAttribute;
            //如果需要验证
            if (qCachingAttribute != null)
            {
                var cachekey = CustomCacheKey(invocation);

                var t = method.GetType();

              //  var 
                var cacheValue = _cacheService.Get (cachekey);

               
                if (cacheValue != null)
                {
                    invocation.ReturnValue = cachekey;
                    return;
                }
                //去执行当前的方法
                invocation.Proceed();
                //存入缓存
                if (!string.IsNullOrEmpty(cachekey))
                {
                    _cacheService.Add(cachekey, invocation.ReturnValue);
                }
            }
            else
            {
                invocation.Proceed();//直接执行被拦截方法
            }

        }
        //自定义缓存键
        private string CustomCacheKey(IInvocation invocation)
        {
            var typeName = invocation.TargetType.Name;
            var methodName = invocation.Method.Name;
            var methodArguments = invocation.Arguments.Select(GetArgumentValue).Take(3).ToList();//获取参数列表，最多三个

            string key = $"{typeName}:{methodName}:";
            foreach (var param in methodArguments)
            {
                key += $"{param}:";
            }

            return key.TrimEnd(':');
        }

        //object 转 string
        private string GetArgumentValue(object arg)
        {
            if (arg is int || arg is long || arg is string)
                return arg.ToString();

            if (arg is DateTime)
                return ((DateTime)arg).ToString("yyyyMMddHHmmss");

            return "";
        }
    }
}
